package demo5_innerclass;

//一个类定义在另一个类或一个方法的内部，前者叫内部类，后者叫外部类
//静态内部类 实例 匿名         普通（定义在方法里）
//demo4包里的Money不是内部类，只是类的组合
//每一个内部类都会生成一个字节码文件

//class A{
//    class B{
//        //实例内部类
//    }
//    static class C{
//        //静态内部类
//    }
//}

//使用的多少：（静态内部类 匿名内部类） （实例内部类） （局部内部类）

interface A{
    void testA();
}

class OuterClass1 {
    public int data1 = 1;
    public int data2 = 2;
    public static int data3 = 3;
    public void method1() {
        System.out.println("外部类方法");
    }
    class InnerClass1 {
        public int data4 = 400;
        public int data1 = 100;
        public void method2() {
            System.out.println("内部类方法");
            System.out.println(data1); //这里会调用内部类的data1,优先在内部类找，找不到的话就去外部类找
            //如果要访问外部类同名成员变量时，要通过外部类名.this.data1访问
            System.out.println(OuterClass1.this.data1);
            System.out.println(this.data1); //这样访问的还是内部类的

            //在实例内部类中可以直接访问外部类中：任意访问限定符修饰的成员
            System.out.println(data2);
            data2 = 200;
            System.out.println(data2);
            method1();
            System.out.println(data3);
            System.out.println(data4);
        }
    }
}

class OuterClass2 {
    public int data1 = 10;
    public int data2 = 20;
    public static int data3 = 30;

    static class InnerClass2 {
        public int data4 = 40;
        public void test() {
            System.out.println(data4);
            System.out.println(data3);
            //System.out.println(data1); 这样会报错，静态内部类不能访问外部类的非静态成员

            //如何访问外部类的非静态的数据成员？
            OuterClass2 outerclass2 = new OuterClass2();
            System.out.println(outerclass2.data1); //new一个外部类对象.就行
        }
    }
}

public class InnerClass_note {
    public static void test() {
        class Inner{
            int n = 911;
        } //这就叫局部内部类，只能定义在方法里，不能用访问限定修饰符修饰
        Inner inner = new Inner();
        System.out.println(inner.n);
        //且只能在方法内使用，不能在方法外使用
    }
    public static void main(String[] args) {
        new A() {
            @Override
            public void testA() {
                System.out.println("哈哈");
            }
        }.testA(); //以上可以认为一个类实现了A接口，然后创建了一个对象，调用了testA方法
        //这就叫匿名内部类，这个类没有名字

        int val = 10;
        //val = 100; 若改成这样会报错，因为匿名内部类能访问的是没有被修改过的数据 -->变量的捕获
        //默认能访问的是final修饰的
        A a = new A(){
            @Override
            public void testA(){
                System.out.println("值：" + val);
            }
        };
        a.testA();

        System.out.println("=========================");
        //如何实例化一个内部类对象
        // 要访问实例内部类中成员，必须要创建实例内部类的对象
        // 而普通内部类定义与外部类成员定义位置相同，因此创建实例内部类对象时必须借助外部类
        OuterClass1.InnerClass1 innerclass1 = new OuterClass1().new InnerClass1();
        //上述语法比较奇怪。也可以先将外部类对象先创建出来，然后再创建实例内部类对象。
        OuterClass1 outerclass1 = new OuterClass1();
        OuterClass1.InnerClass1 innerclass2 = outerclass1.new InnerClass1();
        innerclass2.method2();

        System.out.println("=========================");
        test();
    }
}